package com.yao2san.ssoserver.login.controller;

import com.yao2san.ssoserver.constant.AppConstant;
import com.yao2san.ssoserver.login.service.LoginService;
import com.yao2san.ssoserver.util.CookieUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by wxg on 2019/5/4 19:24
 */
@Controller
public class LoginController {
    private final RedisTemplate<String, String> redisTemplate;
    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
    private final LoginService loginService;

    @Autowired
    public LoginController(LoginService loginService, RedisTemplate<String, String> redisTemplate) {
        this.loginService = loginService;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 登录页面
     *
     * @param originalUrl 源url
     * @param uuid        客户端唯一标识符
     */
    @RequestMapping("/loginPage")
    public String loginPage(String originalUrl, String uuid, HttpServletResponse response) {
        CookieUtil.setCookie(response, "originalUrl", originalUrl, AppConstant.REDIS_TICKET_ALIVE_SECONDS);
        CookieUtil.setCookie(response, "uuid", uuid, AppConstant.REDIS_TICKET_ALIVE_SECONDS);
        return "/login";
    }

    /**
     * 登录验证
     *
     * @param userName 用户名
     * @param password 密码
     */
    @ResponseBody
    @RequestMapping("/login")
    public boolean login(String userName, String password, HttpServletRequest request, HttpServletResponse response) {
        boolean loginSuccess = loginService.login(userName, password);
        if (loginSuccess) {
            //取到客户端唯一标识
            String uuid = CookieUtil.getCookie(request, "uuid");
            //创建ticket
            String ticket = loginService.createTicket(uuid);
            //存redis,测试60秒过期
            redisTemplate.opsForValue().set(AppConstant.REDIS_TICKET_PREFIX + ticket, userName, AppConstant.REDIS_TICKET_ALIVE_SECONDS, TimeUnit.SECONDS);
            //回源url
            String originalUrl = CookieUtil.getCookie(request, "originalUrl") + "?ticket=" + ticket;
            try {
                //重定向到源url
                response.sendRedirect(originalUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return loginSuccess;
    }

    /**
     * 检查ticket
     *
     * @param ticket ticket
     * @param uuid   客户端唯一标识
     */
    @ResponseBody
    @RequestMapping("/checkTicket")
    public String checkTicket(String ticket, String uuid) {

        String oldTicketValue = redisTemplate.opsForValue().get(AppConstant.REDIS_TICKET_PREFIX + ticket);
        //较验ticket
        //当redis存在ticket时验证成功
        if (ticket != null && oldTicketValue != null ) {
            //开启一次性ticket,每次返回新ticket，增强安全性，但是性能会降低
            //注意：开启一次性ticket验证时，uuid和ticket必传
            if(AppConstant.ENABLE_DISPOSABLE_TICKET) {
                //清除旧的ticket
                redisTemplate.delete(AppConstant.REDIS_TICKET_PREFIX + ticket);
                //生成新的ticket
                String newTicket = loginService.createTicket(uuid);
                //保存新的ticket
                redisTemplate.opsForValue().set(AppConstant.REDIS_TICKET_PREFIX + newTicket, oldTicketValue, AppConstant.REDIS_TICKET_ALIVE_SECONDS, TimeUnit.SECONDS);
                //返回新ticket
                return newTicket;
            }else {
                return ticket;
            }
        } else return null;
    }

    /**
     * 获取用户信息
     *
     * @param ticket ticket
     */
    @ResponseBody
    @RequestMapping("/getUserInfo")
    public Map<String, String> getUserInfo(String ticket) {
        //模拟根据ticket获取用户用户名,根据用户名获取用户信息
        String userName = redisTemplate.opsForValue().get(AppConstant.REDIS_TICKET_PREFIX + ticket);
        if (StringUtils.isEmpty(userName)) {
            return null;
        }
        Map<String, String> userInfo = new HashMap<>();
        userInfo.put("userName", userName);
        userInfo.put("ticket", ticket);
        return userInfo;
    }

    @ResponseBody
    @RequestMapping("/logout")
    @SuppressWarnings("all")
    public boolean logout(String ticket){
        return redisTemplate.delete(AppConstant.REDIS_TICKET_PREFIX+ticket);
    }
}
